SIMD 扩展 您所在的位置:网站首页 编译器 simd SIMD 扩展

SIMD 扩展

2023-06-16 00:22| 来源: 网络整理| 查看: 265

SIMD 扩展 项目 04/03/2023

Visual C++ 目前支持 OpenMP 2.0 标准,不过 Visual Studio 2019 现在也提供 SIMD 功能。

备注

若要使用 SIMD,请使用 -openmp:experimental 开关进行编译,该开关使其他 OpenMP 功能在使用 -openmp 开关时不可用。

-openmp:experimental 开关包含 -openmp,这意味着它可使用所有 OpenMP 2.0 功能。

有关详细信息,请参阅 Visual Studio 中 C++ OpenMP 的 SIMD 扩展。

Visual C++ 中的 OpenMP SIMD

OpenMP SIMD 在 OpenMP 4.0 标准中引入,旨在创建向量友好的循环。 在循环之前使用 simd 指令,编译器可以忽略向量依赖项,使循环尽可能友好,并尊重用户同时执行多个循环迭代的意图。

#pragma omp simd for (i = 0; i < count; i++) { a[i] = a[i-1] + 1; b[i] = *c + 1; bar(i); }

Visual C++ 提供类似的非 OpenMP 循环 pragma,例如 #pragma vector 和 #pragma ivdep,但是通过 OpenMP SIMD,编译器可执行更多操作,例如:

始终允许忽略当前的向量依赖项。 在循环中启用 /fp:fast。 外部循环和带有函数调用的循环对向量友好。 嵌套循环可合并为一个循环并对向量友好。 使用 #pragma omp for simd 进行混合加速可实现粗粒度多线程和细粒度向量。

对于向量友好循环,除非使用向量支持日志开关,否则编译器将保持无提示:

cl -O2 -openmp:experimental -Qvec-report:2 mycode.cpp mycode.cpp(84) : info C5002: Omp simd loop not vectorized due to reason '1200' mycode.cpp(90) : info C5002: Omp simd loop not vectorized due to reason '1200' mycode.cpp(96) : info C5001: Omp simd loop vectorized

对于非向量友好循环,编译器会向每个循环发出一条消息:

cl -O2 -openmp:experimental mycode.cpp mycode.cpp(84) : info C5002: Omp simd loop not vectorized due to reason '1200' mycode.cpp(90) : info C5002: Omp simd loop not vectorized due to reason '1200' 子句

OpenMP SIMD 指令还可采用以下子句来增强向量支持:

指令 描述 simdlen(length) 指定向量通道数。 safelen(length) 指定向量依赖项距离。 linear(list[ : linear-step]) 从循环归纳变量到数组订阅的线性映射。 aligned(list[ : alignment]) 数据的对齐方式。 private(list) 指定数据私有化。 lastprivate(list) 使用上次迭代的最终值指定数据私有化。 reduction(reduction-identifier:list) 指定自定义归约操作。 collapse(n) 合并循环嵌套。

备注

编译器会解析并忽略无效的 SIMD 子句,并发出警告。

例如,使用以下代码发出警告:

#pragma omp simd simdlen(8) for (i = 0; i < count; i++) { a[i] = a[i-1] + 1; b[i] = *c + 1; bar(i); } warning C4849: OpenMP 'simdlen' clause ignored in 'simd' directive 示例

OpenMP SIMD 指令为用户提供一种方法来指示编译器使循环对向量友好。 通过使用 OpenMP SIMD 指令批注循环,用户打算同时执行多个循环迭代。

例如,以下循环使用 OpenMP SIMD 指令进行批注。 循环迭代之间没有完美的并行性,因为从 a[i] 到 a[i-1] 存在向后依赖关系,但是由于 SIMD 指令,编译器仍可将第一条语句的连续迭代打包到一个向量指令中,并且并行运行它们。

#pragma omp simd for (i = 0; i < count; i++) { a[i] = a[i-1] + 1; b[i] = *c + 1; bar(i); }

因此,循环的以下转换向量形式是“合法的”,因为编译器保留每个原始循环迭代的顺序行为。 换句话说,a[i] 在 a[-1] 之后执行,b[i] 在 a[i] 之后执行,最后再调用 bar。

for (i = 0; i < count; i+=4) { a[i:i+3] = a[i-1:i+2] + 1; b[i:i+3] = *c + 1; bar(i); bar(i+1); bar(i+2); bar(i+3); }

如果内存引用 *c 可能带有 a[i] 或 b[i] 的别名,则将其移出循环是不合法的。 如果中断顺序依赖关系,那么在一个原始迭代中重新排序语句也是不合法的。 例如,以下转换循环不合法:

c = b; t = *c; for (i = 0; i < count; i+=4) { a[i:i+3] = a[i-1:i+2] + 1; bar(i); // illegal to reorder if bar[i] depends on b[i] b[i:i+3] = t + 1; // illegal to move *c out of the loop bar(i+1); bar(i+2); bar(i+3); } 另请参阅

/openmp(启用 OpenMP 2.0 支持)



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有